#!/usr/bin/python

# Copyright (c) 2009, Purdue University
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 
# Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright notice, this
# list of conditions and the following disclaimer in the documentation and/or
# other materials provided with the distribution.
# 
# Neither the name of the Purdue University nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Config check tool for Roster"""


__copyright__ = 'Copyright (C) 2009, Purdue University'
__license__ = 'BSD'
__version__ = '0.5'


import sys
import os

from optparse import OptionParser

def main(args):
  """Collects command line arguments. Checks configs.

  Inputs:
    args: list of arguments from the command line
  """
  parser = OptionParser()

  parser.add_option('-d', '--directory', action='store', dest='directory',
                    help='Directory to scan.', metavar='<directory>',
                    default=None)
  parser.add_option('-z', '--named-checkzone', action='store',
                    dest='named_checkzone',
                    help='Location of named_checkzone binary.',
                    default='/usr/sbin/named-checkzone')
  parser.add_option('-c', '--named-checkconf', action='store',
                    dest='named_checkconf',
                    help='Location of named_checkconf binary.',
                    default='/usr/sbin/named-checkconf')
  parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
                    help='Make command verbose.', default=False)

  (globals()['options'], args) = parser.parse_args(args)


  if( len(parser.largs) == 1 and not options.directory ):
    options.directory = parser.largs[0]
  if( not options.directory ):
    print 'ERROR: Need to specify a directory.'
  if( not os.path.exists(options.named_checkzone) ):
    print 'ERROR: Could not find "named-checkzone" binary.'
  if( not os.path.exists(options.named_checkconf) ):
    print 'ERROR: Could not find "named-checkconf" binary.'

  named_files = os.popen(
      'ls %s/*/named.conf' % options.directory).read().split()
  for current_file in named_files:
    handle = os.popen('%s %s' % (options.named_checkconf, current_file))
    checknamed_text = handle.read()
    return_val = handle.close()
    if( checknamed_text == '' ):
      if( options.verbose ):
        print 'Finished - %s' % current_file
    else:
      print 'ERROR: %s' % checknamed_text
      sys.exit(1)


  zone_files = os.popen('ls %s/*/*/*.db' % options.directory).read().split()
  for current_file in zone_files:
    file_handle = open(current_file, 'r')
    file_contents = file_handle.read().split('\n')
    file_handle.close()
    for line in file_contents:
      if( line.startswith('$ORIGIN') and len(line.split()) == 2 ):
        origin = line.split()[1]
        break
    else:
      print 'ERROR: Could not find $ORIGIN in "%s"' % current_file
      sys.exit(1)
    handle = os.popen('%s %s %s' % (options.named_checkzone, origin,
                                    current_file))
    checkzone_text = handle.read()
    return_val = handle.close()
    if( checkzone_text.split('\n')[1] == 'OK' ):
      if( options.verbose ):
        print 'Finished - %s' % current_file
    else:
      print 'ERROR: %s' % checkzone_text

  if( options.verbose ):
    print '--------------------------------------------------------------------'
    print 'Checked %s named.conf file(s) and %s zone file(s)\n' % (
        len(named_files), len(zone_files))
    print 'All checks successful'

if __name__ == '__main__':
    main(sys.argv[1:])
